package com.hbnu.system.utils;

import com.hbnu.system.config.BaseException;
import com.hbnu.system.constant.StatusCheckConstant;
import com.hbnu.system.model.entity.Audit;
import com.hbnu.system.service.AuditService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 审核辅助工具类，用于封装通用的“通过审核”与“退回审核”逻辑，减少代码重复。
 * 适用于著作、论文、项目等多个模块的审核流程。
 * @author ：jxl
 * @date ：Created in 2025/7/25
 */
@Component
public class CheckAuditHelper {

    @Autowired
    private AuditService auditService;

    @Autowired
    private UserInfoUtils userInfoUtils;

    /**
     * 通用审核通过逻辑处理
     *
     * @param entity         待更新的实体对象（如：Paper、Work等）
     * @param expectedStatus 当前必须匹配的状态（校验用）
     * @param targetStatus   审核通过后要设置的目标状态
     * @param roleKey        当前操作角色（如：院级审核/校级审核）
     * @param objectLabel    审核对象中文标签（如："论文", "著作"）
     * @param getId          获取对象主键的方法引用
     * @param getStatus      获取对象状态的方法引用
     * @param setStatus      设置对象状态的方法引用
     * @param updateFunc     实际执行数据库更新的函数（返回Boolean表示成功与否）
     * @return               审核操作是否成功
     */
    public <T> Boolean doPassAudit(
            T entity,
            String expectedStatus,
            String targetStatus,
            String roleKey,
            String objectLabel,
            Supplier<String> getId,
            Supplier<String> getStatus,
            Consumer<String> setStatus,
            Function<T, Boolean> updateFunc
    ) {
        // 状态校验
        if (!expectedStatus.equals(getStatus.get())) {
            throw new BaseException(objectLabel + "状态不处于该环节!");
        }

        // 获取当前用户信息
        UserInfoUtils.UserInfo user = userInfoUtils.getCurrentUserInfo();

        // 修改状态
        setStatus.accept(targetStatus);

        // 构造审核记录描述
        String desc = objectLabel + expectedStatus + "->" + roleKey + StatusCheckConstant.CHECK_PASS;

        // 构造审核记录
        Audit audit = AuditUtils.buildAudit(
                getId.get(),
                user.getRoleName(),
                user.getUserName(),
                desc,
                StatusCheckConstant.PASS
        );
        audit.setAuditerTime(LocalDateTime.now());
        auditService.addAudit(audit);

        // 更新数据库
        return updateFunc.apply(entity);
    }

    /**
     * 通用审核退回逻辑处理
     *
     * @param entity         待更新的实体对象
     * @param expectedStatus 当前必须匹配的状态
     * @param backStatus     审核退回后要设置的状态
     * @param reason         退回原因
     * @param objectLabel    审核对象中文标签
     * @param getId          获取对象主键的方法引用
     * @param getStatus      获取对象状态的方法引用
     * @param setStatus      设置对象状态的方法引用
     * @param setReason      设置退回原因的方法引用
     * @param updateFunc     实际执行数据库更新的函数
     * @return               操作是否成功
     */
    public <T> Boolean doBackAudit(
            T entity,
            String expectedStatus,
            String backStatus,
            String reason,
            String objectLabel,
            Supplier<String> getId,
            Supplier<String> getStatus,
            Consumer<String> setStatus,
            Consumer<String> setReason,
            Function<T, Boolean> updateFunc
    ) {
        // 状态校验
        if (!expectedStatus.equals(getStatus.get())) {
            throw new BaseException(objectLabel + "状态不处于该环节!");
        }

        // 获取用户信息
        UserInfoUtils.UserInfo user = userInfoUtils.getCurrentUserInfo();

        // 设置退回状态和原因
        setStatus.accept(backStatus);
        setReason.accept(reason);

        // 构造审核描述
        String desc = objectLabel + expectedStatus + "->被" + user.getRoleName() + "退回";

        // 生成审核记录
        Audit audit = AuditUtils.buildAudit(
                getId.get(),
                user.getRoleName(),
                user.getUserName(),
                desc,
                reason
        );
        audit.setAuditerTime(LocalDateTime.now());
        auditService.addAudit(audit);

        // 更新数据库
        return updateFunc.apply(entity);
    }
}
